package com.easy.back.controller;

import cn.hutool.core.lang.UUID;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CreateCache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easy.back.pojo.EmailBody;
import com.easy.back.pojo.R;
import com.easy.back.pojo.User;
import com.easy.back.service.IUserService;
import com.easy.back.service.IVisitLogService;
import com.easy.back.utils.BaseContext;
import com.easy.back.utils.PasswordEncryptionUtils;
import com.easy.back.utils.ip.IpOrAddress;
import com.easy.back.utils.mq.MessageRocketProducer;
import com.easy.back.utils.sendCode.SMSUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户控制器
 *
 * @author RuoYu
 * @date 2023/01/01
 */
@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    private IUserService userService;

    @Autowired
    private IVisitLogService visitLogService;

    @CreateCache(area = "suiyizu", name = "login_error_", expire = 120, timeUnit = TimeUnit.SECONDS)
    private Cache<String, String> loginError;


    @CreateCache(area = "suiyizu", name = "login_", expire = 300, timeUnit = TimeUnit.SECONDS)
    private Cache<String, String> codeCache;


    @Autowired
    private SMSUtils smsUtils;

    @Autowired
    private MessageRocketProducer messageRocketProducer;

    @GetMapping("/sendCode/{phone}")
    public R getCode(@PathVariable String phone) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);

        User emp = userService.getOne(queryWrapper);
        if (emp == null) {
            return R.error("用户不存在");
        }
        R r = smsUtils.sendMail(emp.getPhone());
        return r;
    }

    @PostMapping("/loginCode")
    public R<User> loginCode(HttpServletRequest request, @RequestBody Map<String, String> user) {
        String phone = user.get("phone");
        String code = user.get("code");
        String s = codeCache.get(phone);
        if (s != null && s.equals(code)) {
            codeCache.remove(phone);
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getPhone, phone);

            User emp = userService.getOne(queryWrapper);
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getUsername, emp.getUsername());
            updateWrapper.set(User::getStatus, 1);
            userService.update(updateWrapper);
            //6、登录成功，将员工id存入Session并返回登录成功结果
            request.getSession().setAttribute("user", emp.getId());

            // 7、添加登录日志
            visitLogService.addVisitLog(emp);
            return R.success(emp);
        }
        return R.error("验证码错误");
    }

    /**
     * 员工登录
     *
     * @param request
     * @param user
     * @return
     */
    @PostMapping("/login")
    public R<User> login(HttpServletRequest request, @RequestBody User user) {
        //1、将页面提交的密码password进行md5加密处理
        String password = PasswordEncryptionUtils.encryption(user.getPassword());

        //2、根据页面提交的用户名username查询数据库
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, user.getUsername());

        User emp = userService.getOne(queryWrapper);
        //3、如果没有查询到则返回登录失败结果
        if (emp == null) {
            return R.error("用户不存在");
        }

        //4、查看员工状态，如果为已禁用状态，则返回员工已禁用结果
        if (emp.getStatus() == 0) {
            return R.error("账号被禁用");
        }
        if (emp.getStatus() == -1) {
            return R.error(-1, "账号异常请用验证码进行登录");
        }
        //5、密码比对，如果不一致则返回登录失败结果
        if (!emp.getPassword().equals(password)) {
            String s = loginError.get(user.getUsername());
            if (s == null) {
                loginError.put(user.getUsername(), "1");
            } else {
                int sum = Integer.parseInt(s) + 1;
                loginError.put(user.getUsername(), String.valueOf(sum));
                if (sum >= 4) {
                    LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(User::getUsername, emp.getUsername());
                    updateWrapper.set(User::getStatus, -1);
                    userService.update(updateWrapper);
                    if (emp.getEmail() != null) {
                        Date date = new Date();
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :HH:mm:ss");
                        String ip = IpOrAddress.getIp();//登录ip
                        String address = IpOrAddress.getAddress();//登录地址
                        EmailBody emailBody = new EmailBody("1", UUID.fastUUID().toString(), emp.getEmail(), emp.getUsername(), dateFormat.format(date), ip, address, null);
                        messageRocketProducer.sendMessage(emailBody);//发送邮件提醒用户
                    }
                }
            }
            return R.error("登陆失败");
        }


        //6、登录成功，将员工id存入Session并返回登录成功结果
        request.getSession().setAttribute("user", emp.getId());

        // 7、添加登录日志
        visitLogService.addVisitLog(emp);
        return R.success(emp);
    }

    /**
     * 员工退出
     *
     * @param request
     */
    @PostMapping("/logout")
    public R<String> logout(HttpServletRequest request) {
        /*清理Session中保存的当前登录员工的id*/
        request.getSession().removeAttribute("user");
        return R.success("退出成功");
    }

    /**
     * 新增员工
     *
     * @param user
     * @return
     */
    @PostMapping("/d")
    public R<String> save(@RequestBody User user) {
        BaseContext.set(user);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, user.getUsername());
        User one = userService.getOne(wrapper);
        if (one != null) {
            BaseContext.setError("账户已存在");
            return R.error("账户已存在");
        }
        LambdaQueryWrapper<User> wrapperPhone = new LambdaQueryWrapper<>();
        wrapperPhone.eq(User::getPhone, user.getPhone());
        User oneP = userService.getOne(wrapperPhone);
        if (oneP != null) {
            BaseContext.setError("手机号已存在");
            return R.error("手机号已存在");
        }
        LambdaQueryWrapper<User> wrapperEmail = new LambdaQueryWrapper<>();
        wrapperEmail.eq(User::getEmail, user.getEmail());
        User oneE = userService.getOne(wrapperEmail);
        if (oneE != null) {
            BaseContext.setError("邮箱已存在");
            return R.error("邮箱已存在");
        }

        String password = PasswordEncryptionUtils.encryption(user.getPassword());
        user.setPassword(password);

        userService.save(user);
        return R.success("新增员工成功");
    }

    @DeleteMapping("/r")
    public R<String> delete(String id) {
        BaseContext.set(id);
        userService.removeById(id);
        return R.success("删除员工成功");
    }

    /**
     * 员工分页信息查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page<User>> getPage(int page, int pageSize, String name) {
        //构造分页构造器
        Page<User> pageInfo = new Page<>(page, pageSize);
        //构造条件构造器
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //添加过滤条件
        lqw.like(Strings.isNotEmpty(name), User::getName, name);
        //添加排序条件
        lqw.orderByDesc(User::getType);
        lqw.orderByDesc(User::getUpdateTime);
        //执行查询
        userService.page(pageInfo, lqw);
        return R.success(pageInfo);
    }

    /**
     * 根据id更改员工信息
     *
     * @param user
     * @return
     */
    @PutMapping("/u")
    public R<String> update(@RequestBody User user) {
        BaseContext.set(user);
        if (user.getPassword() != null) {
            user.setPassword(PasswordEncryptionUtils.encryption(user.getPassword()));
        }

        userService.updateById(user);
        return R.success("员工信息修改成功");
    }

    /**
     * 根据id查询员工信息
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<User> getById(@PathVariable Long id) {
        User byId = userService.getById(id);
        if (byId != null)
            return R.success(byId);
        return R.error("没有查询到对应员工信息");
    }
}